上一篇已經做完了基礎Vulkan教學,這篇是補充資訊。
這篇要把兩個最常卡人的名詞講到清楚:Descriptor Set 跟 Pipeline Layout。
先用生活比喻建立概念,再一步步做一個「一個 UBO + 一張貼圖」的最小可跑範例,最後補上設計心法(全域/材質/物件分層、動態 UBO、Push Constant)與除錯清單。
我們沿用你前面章節的渲染骨架(傳統 Render Pass + Framebuffer,不用 dynamic rendering)。
在 GLSL 你會看到 layout(set = X, binding = Y)
你在 C++ 端建立 DescriptorSetLayout 時,會宣告每個 binding 的型別/數量/可見階段;
建好 Pipeline Layout 後,只能綁定符合該規格的 Descriptor Set。
UBO
(攝影機/光)→ VS 與 FS 都要看combined image sampler
(一張貼圖 + 一個取樣器)→ 只在 FS 用這樣的分層有個好處:
- Set 0(每幀都換)稱為全域資料
- Set 1(材質)比較少換,可以重複使用在多個模型上
常見 3 層分法:
model
/normalMat
,或索引到大型結構(例如 SSBO)→ 可能每 draw 都改。這樣做的好處:綁定頻率清楚(綁得越少的放前面),CPU 指令較少;
此外,Pipeline Layout 不用常換,切換材質或物件時只換對應的 Set。
當你有很多物件,又不想為每個物件分配一個 Descriptor Set,可以用VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
:
vkCmdBindDescriptorSets
時用 dynamic offset 指到本次要用的那段。這能大幅減少「換 Set」的次數,但需要管理好對齊與 offset。
畫面不變/資料沒進 Shader
set/binding
號碼對不上:GLSL 的 layout(set=?, binding=?)
要跟 DescriptorSetLayoutBinding 完全一致。firstSet
。Validation 說 DescriptorType 不相容
sampler2D
,C++ 卻用 SAMPLED_IMAGE
或 SAMPLER
,正確是 COMBINED_IMAGE_SAMPLER
。貼圖全黑
SHADER_READ_ONLY_OPTIMAL
(這個 Render Pass 不會幫你做)。VkDescriptorImageInfo.imageLayout
寫錯。改了 Layout 但 Pipeline 不重建
std140 對齊錯
mat4/vec4
保險;vec3
會補一格(等於 vec4
的大小)。Descriptor Pool 不夠
maxSets
或 poolSizes
太小;請預估幀數/材質數,或多開幾個 Pool。重建 swapchain 後貼圖失效
Descriptor Set 是「把 Buffer/Texture 接到 Shader 的延長線」;
Pipeline Layout 是「告訴 Pipeline 這條延長線的規格」。
先把 全域(Set0)、材質(Set1)、物件(Set2) 分清楚,搭好 Layout → Pool → Set → Update → Bind 這條流水線,你的 Vulkan 程式就能穩定、有條理地把資料送進 GPU,後面加 PBR、骨骼動畫、陰影貼圖就不會亂。
至此,Vulkan的教學結束。